/**
 * Board.m
 * Cocoa Tetris
 *
 * Copyright 2009 Wei Yeh, Evelyn Yung. All rights reserved.
 */

#import "TetrisController.h"

@implementation Board

-(id)initWithFrame:(NSRect)frame 
{
    self = [super initWithFrame:frame];
	if (!self) return nil;
    
	NSLog(@"Setting up board...");
	
	cells = [[NSMutableArray alloc] init];
	
	Cell *cell;
	NSMutableArray *row;
	for (unsigned int y = 0; y < BOARD_LENGTH; y++) {
		row = [[NSMutableArray alloc] init];
		[cells addObject:row];
		for (unsigned int x = 0; x < BOARD_WIDTH; x++) {
			cell = [[Cell alloc] initWithX:x y:y];
			[row addObject:cell];
		}
	}
    return self;
}

-(Cell *)cellAtY:(unsigned int)y x:(unsigned int)x 
{
	return [[cells objectAtIndex:y] objectAtIndex:x];
}

-(void)clearAll
{
	Cell *cell;
	for (unsigned int y = 0; y < BOARD_LENGTH; y++) {
		for (unsigned int x = 0; x < BOARD_WIDTH; x++) {
			cell = [self cellAtY:y x:x];
			[cell unmark];
		}
	}	
	[self display];
}

-(bool)isInBoundsY:(unsigned int)y x:(unsigned int)x
{
	return y >= 0 && x >= 0 &&
	y < BOARD_LENGTH && x < BOARD_WIDTH;
}

-(bool)canMarkCellAtY:(unsigned int)y x:(unsigned int)x
{
	return [self isInBoundsY:y x:x] && ![[self cellAtY:y x:x] isOccupied];
}

-(void)drawRect:(NSRect)boardArea 
{
	[[NSColor grayColor] set];
	NSRectFill(boardArea);
	
	Cell *cell;
    for (unsigned int y = 0; y < BOARD_LENGTH; y++) {
		for (unsigned int x = 0; x < BOARD_WIDTH; x++) {
			cell = [self cellAtY:y x:x];
			[cell display];
		}
	}
}

-(unsigned int)clear
{
	unsigned int numCleared = 0;
	/* Determine which rows to clear. */
	for (unsigned int y = 0; y < BOARD_LENGTH;) {
		if ([self isRowClearable:y]) {
			[self clearRow:y];
			assert([self isRowEmpty:y]);
			numCleared++;
			[self shiftDownFromRow:y+1];
		} else {
			y++;
		}
	}
	return numCleared;
}

-(void)clearRow:(unsigned int)row
{
	Cell* cell;
	for (unsigned int x = 0; x < BOARD_WIDTH; x++) {
		cell = [self cellAtY:row x:x];
		[[cell tetromino] unmarkCell:cell];
	}
}

-(void)shiftDownFromRow:(unsigned int)row
{
	for (unsigned int y = row; y < BOARD_LENGTH; y++) {
		[self shiftDownUnitFromRow:y];
	}
}

-(void)shiftDownUnitFromRow:(unsigned int)row
{
	Cell *cell;
	for (unsigned int x = 0; x < BOARD_WIDTH; x++) {
		cell = [self cellAtY:row x:x];
		if ([cell isOccupied] && [self canMarkCellAtY:(row-1) x:x]) {
			[[cell tetromino] moveDownUnit:cell];
		}
	}
}

-(bool)isRowClearable:(unsigned int)row
{
	for (unsigned int x = 0; x < BOARD_WIDTH; x++) {
		if (![[self cellAtY:row x:x] isOccupied]) {
			return NO;
		}
	}
	return YES;
}

-(bool)isRowEmpty:(unsigned int)row
{
	for (unsigned int x = 0; x < BOARD_WIDTH; x++) {
		if ([[self cellAtY:row x:x] isOccupied]) {
			return NO;
		}
	}
	return YES;
}


-(BOOL)isOpaque
{
	return YES;
}

-(BOOL)acceptsFirstResponder
{
	return YES;
}

-(void)keyDown:(NSEvent *)event
{
	unichar key = [[event characters] characterAtIndex:0];
	[controller move:key];
}

@end
